package com.xlf.service.base.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.xlf.common.auth.util.SecurityUtils;
import com.xlf.common.core.exception.BizException;
import com.xlf.common.core.pojo.vo.UserVO;
import com.xlf.common.core.util.BeanCopyUtils;
import com.xlf.common.core.util.ServletUtils;
import com.xlf.common.core.util.StringUtils;
import com.xlf.common.core.util.page.PageUtils;
import com.xlf.common.core.util.page.TableDataInfo;
import com.xlf.pojo.base.*;
import com.xlf.pojo.constant.Constants;
import com.xlf.pojo.system.SysUser;
import com.xlf.service.base.manager.ProblemCommonService;
import com.xlf.service.base.mapper.*;
import com.xlf.service.base.pojo.dto.ProblemListReqDTO;
import com.xlf.service.base.pojo.vo.ProblemListVO;
import com.xlf.service.base.pojo.vo.ProblemVO;
import com.xlf.service.base.service.ProblemListService;
import com.xlf.service.system.service.impl.CommonUserVOService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.xlf.common.core.util.page.PageUtils.getDataTable;
import static com.xlf.common.core.util.page.PageUtils.startPage;

/**
* @author 小新
* @description 针对表【problem_list】的数据库操作Service实现
* @createDate 2023-10-03 10:17:03
*/
@Service
public class ProblemListServiceImpl extends ServiceImpl<ProblemListMapper, ProblemList>
    implements ProblemListService{


    @Resource
    ProblemProblemListMapper problemProblemListMapper;

    @Resource
    ProblemMapper problemMapper;

    @Resource
    CommonUserVOService commonUserVOService;

    @Resource
    ProblemListMapper problemListMapper;

    @Autowired
    ProblemCommonService problemCommonService;

    @Resource
    DifficultyMapper difficultyMapper;


    @Override
    public List<ProblemList> getList(ProblemList problemList) {

        LambdaQueryWrapper<ProblemList> wrapper = new LambdaQueryWrapper<>();
        wrapper.likeRight(StringUtils.isNotEmpty(problemList.getTitle()),ProblemList::getTitle,problemList.getTitle())
                .eq(problemList.getUserId()!=null,ProblemList::getUserId,problemList.getUserId())
                .eq(problemList.getAuth()!=null,ProblemList::getAuth,problemList.getAuth())
                .eq(problemList.getStatus()!=null,ProblemList::getStatus,problemList.getStatus());
        List<ProblemList> list = list(wrapper);


        if(StringUtils.isNotEmpty(list)){

            Set<String> userIds = list.stream().map(item -> item.getUserId().toString()).collect(Collectors.toSet());

            Map<Long, UserVO> userVOMap = commonUserVOService.getUserInfoMap(userIds);

            list.forEach(item -> {
                item.setProblemNum(getProblemNum(item.getId()));
                item.setUserVO(BeanCopyUtils.copyObject(userVOMap.get(item.getId()), com.xlf.pojo.vo.UserVO.class));
            });

        }

        return list;
    }

    @Override
    public TableDataInfo<ProblemListVO> getList(ProblemListReqDTO problemListReqDTO) {

        QueryWrapper<ProblemList> wrapper = new QueryWrapper<>();

        wrapper.likeRight(StringUtils.isNotEmpty(problemListReqDTO.getTitle()),"title",problemListReqDTO.getTitle())
                .eq(StringUtils.isNotNull(problemListReqDTO.getAuth()),"auth",problemListReqDTO.getAuth())
                .orderByAsc("rank");
        if(StringUtils.isNotEmpty(problemListReqDTO.getNickName())){
            SysUser sysUser = new SysUser();
            sysUser.setNickName(problemListReqDTO.getNickName());
            Map<Long, UserVO> userInfo = commonUserVOService.getUserInfoMap(sysUser);
            if(StringUtils.isEmpty(userInfo))
                return PageUtils.getEmptyDataTable();
            Set<Long> ids = userInfo.keySet();
            wrapper.in("user_id",ids);
        }

        startPage();
        List<ProblemListVO> list = problemListMapper.getList(wrapper);

        if(StringUtils.isNotEmpty(list)){
            Map<Long, UserVO> userInfo = commonUserVOService.getUserInfoMap(list.stream().map(item -> item.getUserId().toString()).collect(Collectors.toSet()));
            list.forEach(item -> {
                item.setProblemNum(getProblemNum(item.getId()));
                item.setUserVO(BeanCopyUtils.copyObject(userInfo.get(item.getUserId()), com.xlf.pojo.vo.UserVO.class));
            });
        }

        return getDataTable(list,new PageInfo(list).getTotal());
    }

    @Transactional
    @Override
    public boolean saveOrUpdate_(ProblemList problemList) {

        Long userId = (Long)SecurityUtils.getUserId();

        problemList.setUserId(userId);
        saveOrUpdate(problemList);

        problemProblemListMapper.delete(new LambdaQueryWrapper<ProblemProblemList>()
                .eq(ProblemProblemList::getProblemListId,problemList.getId()));

        if(StringUtils.isNotEmpty(problemList.getProblemIds())){
            problemList.getProblemIds().forEach(item -> {
                ProblemProblemList problemProblemList = new ProblemProblemList();
                problemProblemList.setProblemId(item);
                problemProblemList.setProblemListId(problemList.getId());
                problemProblemListMapper.insert(problemProblemList);
            });
        }

        return true;
    }

    @Override
    public ProblemList getProblemList(String id) {

        ProblemList problemList = getById(id);

        Set<Long> problemListIds = getProblemIdsByProblemListId(id);

        if(StringUtils.isNotEmpty(problemListIds))
            problemList.setProblemList(problemMapper.selectBatchIds(problemListIds));
        else
            problemList.setProblemList(new ArrayList<>());

        return problemList;
    }

    private Set<Long> getProblemIdsByProblemListId(String id) {

        List<ProblemProblemList> problemProblemLists = problemProblemListMapper.selectList(new LambdaQueryWrapper<ProblemProblemList>()
                .eq(ProblemProblemList::getProblemListId, id));

        Set<Long> collect = new HashSet<>();
        if(StringUtils.isNotEmpty(problemProblemLists)){
           collect = problemProblemLists.stream().map(item -> item.getProblemId()).collect(Collectors.toSet());
        }
        return collect;
    }


    @Override
    public ProblemListVO getProblemListVO(String id) {


        ProblemList problemList = lambdaQuery().eq(ProblemList::getId,id)
                .eq(ProblemList::getStatus, com.xlf.common.core.constant.Constants.NORMAL)
                .one();

        Assert.notNull(problemList,() -> new BizException("题库不存在！"));

        if(Constants.ProblemListAUTH.PRIVATE.getCode().equals(problemList.getAuth())){
            String pwd = ServletUtils.getParameter("pwd");
            if(StringUtils.isEmpty(pwd))
                throw new BizException("题库私有,请输入密码！");
            if(!problemList.getPrivatePwd().equals(pwd))
                throw new BizException("密码错误!");
        }

        ProblemListVO problemListVO = BeanCopyUtils.copyObject(problemList, ProblemListVO.class);

        problemListVO.setProblemNum(getProblemNum(problemList.getId()));

        Set<Long> problemListId = getProblemIdsByProblemListId(id);

        if(StringUtils.isNotEmpty(problemListId)){
            QueryWrapper<ProblemVO> problemQueryWrapper = new QueryWrapper<>();

            problemQueryWrapper.in("t1.id",problemListId)
                    .eq("t1.status",com.xlf.common.core.constant.Constants.NORMAL)
                    .orderByAsc("t1.problem_id")
                    .groupBy("t1.id"); //需要分组
            List<ProblemVO> problemVOList = problemMapper.getProblemVOList(problemQueryWrapper);

            if(StringUtils.isNotEmpty(problemVOList)){
                problemVOList.forEach(item -> {
                    item.setJudgeStatusVOS(problemCommonService.judgeStatusVOList(item.getId()));
                    item.setTagList(problemCommonService
                            .getProblemTags(item.getId(),
                                    wrapper -> wrapper.eq(Tag::getStatus, com.xlf.common.core.constant.Constants.NORMAL)));
                    item.setDifficulty(difficultyMapper.selectById(item.getDifficultyId()));

                });

            }
            problemListVO.setProblemVOList(problemVOList);
        }

        Optional.ofNullable(problemListVO.getUserId()).ifPresent(item -> {
            UserVO userInfo = commonUserVOService.getUserInfo(item);
            problemListVO.setUserVO(BeanCopyUtils.copyObject(userInfo, com.xlf.pojo.vo.UserVO.class));

        });

        return problemListVO;
    }

    private Integer getProblemNum(Long problemListId) {
       return Math.toIntExact(problemProblemListMapper.selectCount(new LambdaQueryWrapper<ProblemProblemList>()
               .eq(ProblemProblemList::getProblemListId, problemListId)));
    }

    @Override
    @Transactional
    public void delete(List<String> ids) {

        Assert.notNull(ids,() -> new BizException("列表不能为空"));
        ids.forEach(item -> {
            Long count = problemProblemListMapper.selectCount(new LambdaQueryWrapper<ProblemProblemList>()
                    .eq(ProblemProblemList::getProblemListId, item));
            if(count > 0){
                throw new BizException("该题单下存在题目，不允许删除！");
            }
            removeById(item);
        });
        return;
    }

    @Override
    public boolean updateStatus(ProblemList problemList) {
        return lambdaUpdate().set(ProblemList::getStatus,problemList.getStatus()).eq(ProblemList::getId,problemList.getId()).update();

    }
}




